<template>
  <div class="node-test">
    <div class="test-header">
      <h3>{{ nodeData.nodeName }} - 节点测试</h3>
      <p class="test-desc">{{ nodeData.description }}</p>
    </div>

    <div class="test-content">
      <el-row :gutter="20">
        <!-- 输入参数配置 -->
        <el-col :span="12">
          <el-card class="test-section" shadow="never">
            <template #header>
              <div class="section-header">
                <span class="section-title">输入参数</span>
                <el-button
                  type="primary"
                  size="small"
                  @click="generateSampleInput"
                >
                  生成示例数据
                </el-button>
              </div>
            </template>
            
            <div class="input-editor">
              <el-tabs v-model="inputTab" type="border-card">
                <el-tab-pane label="JSON编辑" name="json">
                  <el-input
                    v-model="testInput"
                    type="textarea"
                    :rows="12"
                    placeholder="请输入测试数据（JSON格式）"
                    class="json-input"
                  />
                </el-tab-pane>
                <el-tab-pane label="表单编辑" name="form">
                  <div class="form-editor">
                    <DynamicForm
                      v-if="inputSchema"
                      :schema="inputSchema"
                      :model-value="inputFormData"
                      @update:model-value="handleInputFormChange"
                    />
                  </div>
                </el-tab-pane>
              </el-tabs>
            </div>
          </el-card>
        </el-col>

        <!-- 配置参数 -->
        <el-col :span="12">
          <el-card class="test-section" shadow="never">
            <template #header>
              <div class="section-header">
                <span class="section-title">配置参数</span>
                <el-button
                  type="primary"
                  size="small"
                  @click="loadDefaultConfig"
                >
                  加载默认配置
                </el-button>
              </div>
            </template>
            
            <div class="config-editor">
              <el-tabs v-model="configTab" type="border-card">
                <el-tab-pane label="JSON编辑" name="json">
                  <el-input
                    v-model="testConfig"
                    type="textarea"
                    :rows="12"
                    placeholder="请输入配置参数（JSON格式）"
                    class="json-input"
                  />
                </el-tab-pane>
                <el-tab-pane label="表单编辑" name="form">
                  <div class="form-editor">
                    <DynamicForm
                      v-if="configSchema"
                      :schema="configSchema"
                      :model-value="configFormData"
                      @update:model-value="handleConfigFormChange"
                    />
                  </div>
                </el-tab-pane>
              </el-tabs>
            </div>
          </el-card>
        </el-col>
      </el-row>

      <!-- 测试控制 -->
      <div class="test-controls">
        <el-card shadow="never">
          <div class="controls-content">
            <div class="control-buttons">
              <el-button
                type="primary"
                size="large"
                @click="runTest"
                :loading="testing"
                :icon="VideoPlay"
              >
                {{ testing ? '测试中...' : '运行测试' }}
              </el-button>
              <el-button
                size="large"
                @click="clearResults"
                :icon="Delete"
              >
                清空结果
              </el-button>
              <el-button
                size="large"
                @click="saveTestCase"
                :icon="DocumentAdd"
              >
                保存测试用例
              </el-button>
            </div>
            
            <div class="test-options">
              <el-form inline size="small">
                <el-form-item label="超时时间">
                  <el-input-number
                    v-model="testOptions.timeout"
                    :min="1"
                    :max="300"
                    suffix="秒"
                    style="width: 120px"
                  />
                </el-form-item>
                <el-form-item label="重试次数">
                  <el-input-number
                    v-model="testOptions.retryCount"
                    :min="0"
                    :max="5"
                    style="width: 120px"
                  />
                </el-form-item>
                <el-form-item label="调试模式">
                  <el-switch v-model="testOptions.debug" />
                </el-form-item>
              </el-form>
            </div>
          </div>
        </el-card>
      </div>

      <!-- 测试结果 -->
      <div class="test-results">
        <el-card shadow="never">
          <template #header>
            <div class="section-header">
              <span class="section-title">测试结果</span>
              <div class="result-status">
                <el-tag
                  v-if="lastTestResult"
                  :type="lastTestResult.success ? 'success' : 'danger'"
                  size="large"
                >
                  {{ lastTestResult.success ? '测试通过' : '测试失败' }}
                </el-tag>
              </div>
            </div>
          </template>
          
          <div v-if="testResults.length === 0" class="no-results">
            <el-empty description="暂无测试结果" />
          </div>
          
          <div v-else class="results-list">
            <el-collapse v-model="activeResults">
              <el-collapse-item
                v-for="(result, index) in testResults"
                :key="index"
                :name="index"
              >
                <template #title>
                  <div class="result-title">
                    <el-tag
                      :type="result.success ? 'success' : 'danger'"
                      size="small"
                    >
                      {{ result.success ? '成功' : '失败' }}
                    </el-tag>
                    <span class="result-time">{{ result.timestamp }}</span>
                    <span class="result-duration">耗时: {{ result.duration }}ms</span>
                  </div>
                </template>
                
                <div class="result-content">
                  <el-tabs type="border-card">
                    <el-tab-pane label="输出结果" name="output">
                      <pre class="result-json">{{ formatJson(result.output) }}</pre>
                    </el-tab-pane>
                    <el-tab-pane label="执行日志" name="logs">
                      <div class="log-list">
                        <div
                          v-for="(log, logIndex) in result.logs"
                          :key="logIndex"
                          :class="['log-item', `log-${log.level}`]"
                        >
                          <span class="log-time">{{ log.timestamp }}</span>
                          <span class="log-level">{{ log.level.toUpperCase() }}</span>
                          <span class="log-message">{{ log.message }}</span>
                        </div>
                      </div>
                    </el-tab-pane>
                    <el-tab-pane label="错误信息" name="error" v-if="!result.success">
                      <div class="error-info">
                        <el-alert
                          :title="result.error.message"
                          type="error"
                          :description="result.error.stack"
                          show-icon
                          :closable="false"
                        />
                      </div>
                    </el-tab-pane>
                    <el-tab-pane label="性能指标" name="metrics">
                      <div class="metrics-info">
                        <el-descriptions :column="2" border>
                          <el-descriptions-item label="执行时间">
                            {{ result.duration }}ms
                          </el-descriptions-item>
                          <el-descriptions-item label="内存使用">
                            {{ result.metrics?.memoryUsage || 'N/A' }}
                          </el-descriptions-item>
                          <el-descriptions-item label="CPU使用">
                            {{ result.metrics?.cpuUsage || 'N/A' }}
                          </el-descriptions-item>
                          <el-descriptions-item label="网络请求">
                            {{ result.metrics?.networkRequests || 0 }}
                          </el-descriptions-item>
                        </el-descriptions>
                      </div>
                    </el-tab-pane>
                  </el-tabs>
                </div>
              </el-collapse-item>
            </el-collapse>
          </div>
        </el-card>
      </div>
    </div>

    <!-- 测试用例保存对话框 -->
    <el-dialog
      v-model="saveDialogVisible"
      title="保存测试用例"
      width="50%"
      :close-on-click-modal="false"
    >
      <el-form :model="testCaseForm" label-width="100px">
        <el-form-item label="用例名称" required>
          <el-input v-model="testCaseForm.name" placeholder="请输入测试用例名称" />
        </el-form-item>
        <el-form-item label="用例描述">
          <el-input
            v-model="testCaseForm.description"
            type="textarea"
            :rows="3"
            placeholder="请输入测试用例描述"
          />
        </el-form-item>
        <el-form-item label="标签">
          <el-select
            v-model="testCaseForm.tags"
            multiple
            filterable
            allow-create
            placeholder="请选择或输入标签"
            style="width: 100%"
          >
            <el-option label="功能测试" value="功能测试" />
            <el-option label="性能测试" value="性能测试" />
            <el-option label="边界测试" value="边界测试" />
            <el-option label="异常测试" value="异常测试" />
          </el-select>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="saveDialogVisible = false">取消</el-button>
          <el-button type="primary" @click="confirmSaveTestCase">保存</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, reactive, computed, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import {
  VideoPlay,
  Delete,
  DocumentAdd
} from '@element-plus/icons-vue'
import DynamicForm from './DynamicForm.vue'
import * as nodeDefinitionApi from '@/api/nodeDefinition'

// Props
const props = defineProps({
  nodeData: {
    type: Object,
    required: true
  }
})

// Emits
const emit = defineEmits(['close'])

// 响应式数据
const testing = ref(false)
const inputTab = ref('json')
const configTab = ref('json')
const activeResults = ref([])
const saveDialogVisible = ref(false)

const testInput = ref('')
const testConfig = ref('')
const inputFormData = ref({})
const configFormData = ref({})

const testResults = ref([])
const lastTestResult = ref(null)

// 测试选项
const testOptions = reactive({
  timeout: 30,
  retryCount: 0,
  debug: false
})

// 测试用例表单
const testCaseForm = reactive({
  name: '',
  description: '',
  tags: []
})

// 计算属性
const inputSchema = computed(() => {
  try {
    // 优先使用前端字段名，如果不存在则尝试使用后端字段名
    const schemaData = props.nodeData.inputParamsSchema || props.nodeData.inputSchema
    return schemaData
      ? (typeof schemaData === 'string'
          ? JSON.parse(schemaData)
          : schemaData)
      : null
  } catch {
    return null
  }
})

const configSchema = computed(() => {
  try {
    // 优先使用前端字段名，如果不存在则尝试使用后端字段名
    const schemaData = props.nodeData.configParamsSchema || props.nodeData.configSchema
    return schemaData
      ? (typeof schemaData === 'string'
          ? JSON.parse(schemaData)
          : schemaData)
      : null
  } catch {
    return null
  }
})

// 方法定义
const generateSampleInput = () => {
  if (inputSchema.value) {
    const sample = generateSampleData(inputSchema.value)
    testInput.value = JSON.stringify(sample, null, 2)
    inputFormData.value = sample
  } else {
    const defaultInput = {
      data: {
        message: 'Hello World',
        timestamp: new Date().toISOString()
      },
      context: {
        userId: 'user123',
        requestId: 'req-' + Date.now()
      }
    }
    testInput.value = JSON.stringify(defaultInput, null, 2)
    inputFormData.value = defaultInput
  }
}

const loadDefaultConfig = () => {
  if (props.nodeData.defaultConfig) {
    const defaultConfig = typeof props.nodeData.defaultConfig === 'string'
      ? JSON.parse(props.nodeData.defaultConfig)
      : props.nodeData.defaultConfig
    testConfig.value = JSON.stringify(defaultConfig, null, 2)
    configFormData.value = defaultConfig
  } else if (configSchema.value) {
    const sample = generateSampleData(configSchema.value)
    testConfig.value = JSON.stringify(sample, null, 2)
    configFormData.value = sample
  }
}

const generateSampleData = (schema) => {
  if (!schema || typeof schema !== 'object') return {}
  
  const sample = {}
  
  if (schema.type === 'object' && schema.properties) {
    Object.entries(schema.properties).forEach(([key, prop]) => {
      sample[key] = generateSampleValue(prop)
    })
  }
  
  return sample
}

const generateSampleValue = (prop) => {
  if (prop.default !== undefined) {
    return prop.default
  }
  
  switch (prop.type) {
    case 'string':
      return prop.enum ? prop.enum[0] : 'sample string'
    case 'number':
      return prop.minimum || 0
    case 'integer':
      return prop.minimum || 1
    case 'boolean':
      return true
    case 'array':
      return []
    case 'object':
      return {}
    default:
      return null
  }
}

const handleInputFormChange = (data) => {
  inputFormData.value = data
  testInput.value = JSON.stringify(data, null, 2)
}

const handleConfigFormChange = (data) => {
  configFormData.value = data
  testConfig.value = JSON.stringify(data, null, 2)
}

const runTest = async () => {
  testing.value = true
  const startTime = Date.now()
  
  try {
    // 验证输入数据
    let inputData = {}
    let configData = {}
    
    if (testInput.value) {
      try {
        inputData = JSON.parse(testInput.value)
      } catch (error) {
        throw new Error('输入参数JSON格式错误：' + error.message)
      }
    }
    
    if (testConfig.value) {
      try {
        configData = JSON.parse(testConfig.value)
      } catch (error) {
        throw new Error('配置参数JSON格式错误：' + error.message)
      }
    }
    
    // 调用测试API
    const response = await nodeDefinitionApi.testNodeDefinition(props.nodeData.id, {
      input: inputData,
      config: configData,
      options: testOptions
    })
    
    const duration = Date.now() - startTime
    
    const result = {
      success: response.data.success,
      output: response.data.output,
      logs: response.data.logs || [],
      metrics: response.data.metrics || {},
      duration,
      timestamp: new Date().toLocaleString(),
      error: response.data.error
    }
    
    testResults.value.unshift(result)
    lastTestResult.value = result
    activeResults.value = [0]
    
    if (result.success) {
      ElMessage.success('测试执行成功')
    } else {
      ElMessage.error('测试执行失败：' + (result.error?.message || '未知错误'))
    }
  } catch (error) {
    const duration = Date.now() - startTime
    
    const result = {
      success: false,
      output: null,
      logs: [],
      metrics: {},
      duration,
      timestamp: new Date().toLocaleString(),
      error: {
        message: error.message,
        stack: error.stack
      }
    }
    
    testResults.value.unshift(result)
    lastTestResult.value = result
    activeResults.value = [0]
    
    ElMessage.error('测试执行失败：' + error.message)
  } finally {
    testing.value = false
  }
}

const clearResults = () => {
  testResults.value = []
  lastTestResult.value = null
  activeResults.value = []
  ElMessage.success('测试结果已清空')
}

const saveTestCase = () => {
  if (!testInput.value && !testConfig.value) {
    ElMessage.warning('请先配置测试数据')
    return
  }
  
  testCaseForm.name = `${props.nodeData.nodeName}_测试用例_${Date.now()}`
  testCaseForm.description = `${props.nodeData.nodeName}的测试用例`
  testCaseForm.tags = ['功能测试']
  saveDialogVisible.value = true
}

const confirmSaveTestCase = async () => {
  try {
    const testCase = {
      nodeId: props.nodeData.id,
      name: testCaseForm.name,
      description: testCaseForm.description,
      tags: testCaseForm.tags,
      input: testInput.value ? JSON.parse(testInput.value) : {},
      config: testConfig.value ? JSON.parse(testConfig.value) : {},
      options: testOptions
    }
    
    // 这里应该调用保存测试用例的API
    // await nodeDefinitionApi.saveTestCase(testCase)
    
    ElMessage.success('测试用例保存成功')
    saveDialogVisible.value = false
  } catch (error) {
    ElMessage.error('保存测试用例失败：' + error.message)
  }
}

const formatJson = (data) => {
  try {
    return JSON.stringify(data, null, 2)
  } catch {
    return String(data)
  }
}

// 生命周期
onMounted(() => {
  generateSampleInput()
  loadDefaultConfig()
})
</script>

<style scoped>
.node-test {
  height: 80vh;
  display: flex;
  flex-direction: column;
}

.test-header {
  margin-bottom: 20px;
}

.test-header h3 {
  margin: 0 0 8px 0;
  color: #303133;
}

.test-desc {
  margin: 0;
  color: #606266;
  font-size: 14px;
}

.test-content {
  flex: 1;
  overflow-y: auto;
}

.test-section {
  height: 400px;
  margin-bottom: 20px;
}

.test-section :deep(.el-card__body) {
  height: calc(100% - 60px);
  padding: 0;
}

.section-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.section-title {
  font-weight: 600;
  color: #303133;
}

.input-editor,
.config-editor {
  height: 100%;
}

.input-editor :deep(.el-tabs__content),
.config-editor :deep(.el-tabs__content) {
  height: calc(100% - 40px);
  padding: 16px;
}

.json-input :deep(.el-textarea__inner) {
  font-family: 'Courier New', monospace;
  font-size: 14px;
  line-height: 1.5;
}

.form-editor {
  height: 100%;
  overflow-y: auto;
}

.test-controls {
  margin-bottom: 20px;
}

.controls-content {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 20px;
}

.control-buttons {
  display: flex;
  gap: 12px;
}

.test-options {
  display: flex;
  align-items: center;
}

.test-results {
  min-height: 300px;
}

.no-results {
  padding: 40px 0;
}

.result-title {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
}

.result-time {
  color: #606266;
  font-size: 14px;
}

.result-duration {
  color: #909399;
  font-size: 12px;
  margin-left: auto;
}

.result-content {
  margin-top: 12px;
}

.result-json {
  background: #f5f7fa;
  border: 1px solid #e4e7ed;
  border-radius: 4px;
  padding: 16px;
  font-family: 'Courier New', monospace;
  font-size: 14px;
  line-height: 1.5;
  overflow-x: auto;
  white-space: pre-wrap;
  word-wrap: break-word;
  max-height: 300px;
  overflow-y: auto;
}

.log-list {
  max-height: 300px;
  overflow-y: auto;
}

.log-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 12px;
  border-bottom: 1px solid #f0f0f0;
  font-family: 'Courier New', monospace;
  font-size: 13px;
}

.log-time {
  color: #909399;
  min-width: 120px;
}

.log-level {
  min-width: 60px;
  font-weight: 600;
}

.log-info .log-level {
  color: #409eff;
}

.log-warn .log-level {
  color: #e6a23c;
}

.log-error .log-level {
  color: #f56c6c;
}

.log-debug .log-level {
  color: #909399;
}

.log-message {
  flex: 1;
  word-break: break-all;
}

.error-info {
  padding: 16px;
}

.metrics-info {
  padding: 16px;
}

.result-status {
  display: flex;
  align-items: center;
}

.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
}
</style>